<template>
  <el-form
    class="ui-form"
    :class="[{'is-padding': innerPadding, 'has-toolbar': $slots.toolbar, 'is-fixed-height': fixedHeight, 'is-fixed-toolbar': fixedToolbar }, 'ui-form--' + type]"
    ref="form"
    :rules="innerRules"
    :model="model"
    :label-width="labelWidth"
    :label-position="labelPosition"
    @submit.native.prevent
    :style="style"
  >
    <div class="ui-form__body">
      <slot></slot>
    </div>
    <div class="ui-form__toolbar" v-if="$slots.toolbar" :style="toolbarStyle">
      <slot name="toolbar"></slot>
    </div>
    <div class="ui-form__loading" v-if="loading">
      <ui-loading></ui-loading>
    </div>
  </el-form>
</template>
<script>
import Form from 'element-ui/lib/form'
import 'element-ui/lib/theme-chalk/form.css'
import UiLoading from '../loading'

export default {
  name: 'UiForm',
  components: {
    UiLoading,
    ElForm: Form
  },
  inject: {
    UiDialog: {
      default: null
    }
  },
  props: {
    model: {
      type: Object,
      default: () => ({})
    },
    height: {
      type: String,
      default: 'auto'
    },
    rules: {
      type: Object,
      default: () => ({})
    },
    type: {
      type: String,
      default: 'default',
      validator (value) {
        return ['compact', 'default'].includes(value)
      }
    },
    padding: {
      type: [String, Boolean],
      default: true
    },
    labelWidth: {
      type: String,
      default: '60px'
    },
    labelPosition: {
      type: String,
      default: 'left'
    },
    fixedToolbar: {
      type: Boolean,
      default: false
    },
    queryMethod: {
      type: Function
    }
  },
  data () {
    return {
      loading: false,
      toolbarRect: {}
    }
  },
  computed: {
    style () {
      const style = {}
      if (this.height !== 'auto') {
        style.height = this.height
      }
      return style
    },
    fixedHeight () {
      return this.height !== 'auto'
    },
    innerRules() {
      return this.rules
    },
    innerPadding() {
      if (typeof this.padding !== 'undefined') {
        return !!this.padding
      }
      if (this.UiDialog) {
        return true
      }
      return false
    },
    toolbarStyle () {
      if (!this.fixedToolbar) {
        return
      }
      return {
        position: 'fixed',
        left: this.toolbarRect.left + 'px',
        right: 0,
        width: this.toolbarRect.width + 'px',
        bottom: this.toolbarRect.bottom + 'px'
      }
    }
  },
  created () {
    if (this.queryMethod) {
      this.loadData()
    }
  },
  mounted () {
    this.doLayout()
    window.addEventListener('resize', this.handleWindowResize)
  },
  methods: {
    loadData () {
      if (!this.queryMethod) {
        return Promise.reject('缺少queryMethod配置')
      }
      const rs = this.queryMethod()
      if (rs && rs.then) {
        this.loading = true
        rs.finally(() => {
          this.loading = false
        })
      }
    },
    handleWindowResize () {
      this.doLayout()
    },
    doLayout () {
      if (!this.fixedToolbar) {
        return
      }
      const formRect = this.$el.getBoundingClientRect()
      const toolbarRect = {
        left: formRect.left,
        width: formRect.width,
        bottom: formRect.bottom >= window.innerHeight ? 0 : window.innerHeight - formRect.bottom
      }
      this.toolbarRect = toolbarRect
    },
    validate() {
      return new Promise((resolve, reject) => {
        this.$refs.form.validate((result) => {
          result ? resolve() : reject()
        })
      })
    },
    clearValidate() {
      this.$refs.form.clearValidate()
    },
    resetFields() {
      this.$refs.form.resetFields()
    }
  }
}
</script>
<style lang="less">
.ui-dialog {
  .el-dialog__body > .ui-form {
    .ui-form__toolbar{
      padding: 12px 20px;
      border-top: 1px solid #eee;
    }
  }
}
.ui-drawer {
  .ui-drawer__body > .ui-form {
    .ui-form__body{
      padding: 0 24px;
    }
    .ui-form__toolbar{
      padding: 12px 20px;
      border-top: 1px solid #eee;
    }
  }
}
.ui-form {
  min-height: 100%;
  box-sizing: border-box;
  position: relative;
  &.is-padding{
    > .ui-form__body{
      padding: 20px;
    }
  }
  &.is-fixed-height{
    display: flex;
    flex-direction: column;
    > .ui-form__body{
      flex: 1;
      min-height: 0;
      overflow: auto;
    }
  }
  &.is-fixed-toolbar{
    &.has-toolbar{
      padding-bottom: 62px;
    }
  }
  &.el-form--label-top .el-form-item.is-required {
    .el-form-item__label{
      &:before{
        display: none;
      }
      &:after{
        content: '*';
        color: #F56C6C;
        margin-left: 4px;
      }
    }
  }
  .el-form-item__label{
    color: #888;
  }
}
.ui-form--compact{
  .ui-form-item.el-form-item{
    margin-bottom: 6px;
  }
}
.ui-form__toolbar{
  padding: 12px 22px;
  border-top: 1px solid #eee;
  box-sizing: border-box;
  background-color: #fff;
  z-index: 10;
  border-bottom-left-radius: 3px;
  border-bottom-right-radius: 3px;
}
.ui-form__loading{
  position: absolute;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  z-index: 3;
  background-color: #fff;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}
</style>
